﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Web.Services.Protocols;

#endregion


namespace ESF.General.Network
{
	public static class WebRequestHelper
	{
		#region Enumeraciones

		public enum RequestMethod
		{
			GET,
			POST
		}

		#endregion


		#region Constantes

		// 5 minutos
		public const int DEFAULT_TIMEOUT = 300000;

		#endregion


		#region Propiedades

		public static Uri GetWebProxy (WebRequest pRequest, out bool isByPassed)
		{
			Uri proxyUri;


			if (pRequest.Proxy == null) { isByPassed = false; return null; }
				
			isByPassed = pRequest.Proxy.IsBypassed (pRequest.RequestUri);

			proxyUri = pRequest.Proxy.GetProxy (pRequest.RequestUri); 

			if (proxyUri == pRequest.RequestUri)
			{
				return null;
			}

			return proxyUri;
		}

		#endregion


		#region Funciones

		public static WebRequest CreateRequest (string pURL)
		{
			return CreateRequest (pURL, RequestMethod.GET);
		}


		public static WebRequest CreateRequest (string pURL, RequestMethod pMethod)
		{
			return CreateRequest (pURL, pMethod, null);
		}


		public static WebRequest CreateRequest (string pURL, RequestMethod pMethod, NameValueCollection pParameters)
		{
			return CreateRequest (pURL, pMethod, pParameters, DEFAULT_TIMEOUT);
		}
		
		
		public static WebRequest CreateRequest (string pURL, RequestMethod pMethod, NameValueCollection pParameters, int pTimeoutMs)
		{
			WebRequest theRequest;
			
			StringBuilder parameters;


			if (pParameters != null && pParameters.Count > 0 && pMethod == RequestMethod.GET)
			{
				parameters = new StringBuilder ();

				foreach (string key in pParameters.AllKeys)
				{
					parameters.AppendFormat ("{0}={1}&", key, pParameters [key]);
				}

				parameters.Length -= 1;

				pURL += "?" + parameters.ToString ();
			}

			
			theRequest = WebRequest.Create (pURL);
			theRequest.Proxy = WebRequest.DefaultWebProxy;
			theRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
			theRequest.Method = pMethod.ToString ();
			theRequest.Timeout = pTimeoutMs;
			theRequest.ContentType="application/x-www-form-urlencoded";
			
			return theRequest;
		}


		public static string GetResponse (WebRequest pRequest, NameValueCollection pParameters, out long timeEllapsedMs, out HttpStatusCode pStatusCode, out string pStatusDescription)
		{
			Stopwatch stopwatch;

			StringBuilder parameters;


			parameters = new StringBuilder ();

			stopwatch = new Stopwatch ();

			stopwatch.Start ();
			

			if (pRequest.Method == "POST")
			{
				// Revisar si poner HttpUtility.UrlEncode con dependencia web
				if (pParameters != null && pParameters.Count > 0)
				{
					foreach (string key in pParameters.AllKeys)
					{
						parameters.AppendFormat ("{0}={1}&", key, pParameters [key]);
					}

					parameters.Length -= 1;
				}

				pRequest.ContentLength = parameters.Length;

				// We write the parameters into the request
				StreamWriter sw = new StreamWriter (pRequest.GetRequestStream());
  				sw.Write(parameters.ToString ());
  				sw.Close();
			}
			
			// Execute the query
			try
			{
				HttpWebResponse theResponse =  (HttpWebResponse) pRequest.GetResponse();
			
				pStatusCode = theResponse.StatusCode;
				pStatusDescription = theResponse.StatusDescription; 

				StreamReader sr = new StreamReader(theResponse.GetResponseStream());

				return sr.ReadToEnd();
			}
			catch (WebException pEx)
			{
				if (pEx.Response != null)  
				{
					using (HttpWebResponse errorResponse = (HttpWebResponse) pEx.Response)  
					{  
						pStatusDescription = errorResponse.StatusDescription;
						pStatusCode = errorResponse.StatusCode;

						StreamReader sr = new StreamReader(errorResponse.GetResponseStream());

						return sr.ReadToEnd();
					}
				}
				
				pStatusDescription = "No available";
				pStatusCode = HttpStatusCode.NoContent;

				return pEx.Message;
			}
			finally
			{
				stopwatch.Stop ();

				timeEllapsedMs = stopwatch.ElapsedMilliseconds;
			}   			
		}

		#endregion
	}
}
